var t = [0];
var primes = t;
var pows = t;
var s_i = t, s_i2 = t, s_R = t, s_rm = t, s_q = t, s_n1 = t;
var s_a = t, s_r2 = t, s_n = t, s_b = t, s_d = t, s_x1 = t, s_x2 = t, s_aa = t;
//globals
var bpe = 0;         //bits stored per array element
var mask = 0;        //AND this with an array element to chop it down to bpe bits
var radix = mask + 1;  //equals 2^bpe.  A single 1 bit to the left of the last bit of mask.

//do x=y on bigInts x and y.  x must be an array at least as big as y (not counting the leading zeros in y).
function copy_(x, y) {
    var i;
    var k = x.length < y.length ? x.length : y.length;
    for (i = 0; i < k; i++)
        x[i] = y[i];
    for (i = k; i < x.length; i++)
        x[i] = 0;
}
//do x=y on bigInt x and integer y.
function copyInt_(x, n) {
    var i, c;
    for (c = n, i = 0; i < x.length; i++) {
        x[i] = c & mask;
        c >>= bpe;
    }
}


//returns a duplicate of bigInt x
function dup(x) {
    var i;
    var buff = new Array(x.length);
    copy_(buff, x);
    return buff;
}

//return array of all primes less than integer n
function findPrimes(n) {
    var i, s, p, ans;
    s = new Array(n);
    for (i = 0; i < n; i++)
        s[i] = 0;
    s[0] = 2;
    p = 0;    //first p elements of s are primes, the rest are a sieve
    for (; s[p] < n;) {                  //s[p] is the pth prime
        for (i = s[p] * s[p]; i < n; i += s[p]) //mark multiples of s[p]
            s[i] = 1;
        p++;
        s[p] = s[p - 1] + 1;
        for (; s[p] < n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
    }
    ans = new Array(p);
    for (i = 0; i < p; i++)
        ans[i] = s[i];
    return ans;
}
var trueRandom = function () { return Math.random(); };
//do carries and borrows so each element of the bigInt x fits in bpe bits.
function carry_(x) {
    var i, k, c, b;
    k = x.length;
    c = 0;
    for (i = 0; i < k; i++) {
        c += x[i];
        b = 0;
        if (c < 0) {
            b = -(c >> bpe);
            c += b * radix;
        }
        x[i] = c & mask;
        c = (c >> bpe) - b;
    }
}
function divide_(x, y, q, r) { }
function bitSize(s) { }
function randBigInt_(sR, z, zero) { }
function greater(si, sR) { return false; }
function addInt_(a, b) { }
function add_(a, b) { }
function multInt_(a, b) { }
function mult_(a, b) { }
function modInt(a, b) { return 0; }
function equalsInt(a, b) { return true; }
function millerRabinInt(a, b) { return true; }
function powMod_(a, b, c) { }
function isZero(a) { return true; }
function GCD_(a, b) { }

function randTruePrime_(ans, k) {
    var c, m, pm, dd, j, r, B, divisible, w, z, zz, recSize;

    if (primes.length == 0)
        primes = findPrimes(30000);  //check for divisibility by primes <=30000

    if (pows.length == 0) {
        pows = new Array(512);
        for (j = 0; j < 512; j++) {
            pows[j] = Math.pow(2, j / 511. - 1.);
        }
    }

    //c and m should be tuned for a particular machine and value of k, to maximize speed
    c = 0.1;  //c=0.1 in HAC
    m = 20;   //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
    var recLimit = 20; //stop recursion when k <=recLimit.  Must have recLimit >= 2

    if (s_i2.length != ans.length) {
        s_i2 = dup(ans);
        s_R = dup(ans);
        s_n1 = dup(ans);
        s_r2 = dup(ans);
        s_d = dup(ans);
        s_x1 = dup(ans);
        s_x2 = dup(ans);
        s_b = dup(ans);
        s_n = dup(ans);
        s_i = dup(ans);
        s_rm = dup(ans);
        s_q = dup(ans);
        s_a = dup(ans);
        s_aa = dup(ans);
    }

    if (k <= recLimit) {  //generate small random primes by trial division up to its square root
        pm = (1 << ((k + 2) >> 1)) - 1; //pm is binary number with all ones, just over sqrt(2^k)
        copyInt_(ans, 0);
        for (dd = 1; dd;) {
            dd = 0;
            ans[0] = 1 | (1 << (k - 1)) | Math.floor(trueRandom() * (1 << k));  //random, k-bit, odd integer, with msb 1
            for (j = 1; (j < primes.length) && ((primes[j] & pm) == primes[j]); j++) { //trial division by all primes 3...sqrt(2^k)
                if (0 == (ans[0] % primes[j])) {
                    dd = 1;
                    break;
                }
            }
        }
        carry_(ans);
        return;
    }

    B = c * k * k;    //try small primes up to B (or all the primes[] array if the largest is less than B).
    if (k > 2 * m)  //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
        for (r = 1; k - k * r <= m;)
            r = pows[Math.floor(trueRandom() * 512)];   //r=Math.pow(2,Math.random()-1);
    else
        r = .5;

    //simulation suggests the more complex algorithm using r=.333 is only slightly faster.

    recSize = Math.floor(r * k) + 1;

    randTruePrime_(s_q, recSize);
    copyInt_(s_i2, 0);
    s_i2[Math.floor((k - 2) / bpe)] |= (1 << ((k - 2) % bpe));   //s_i2=2^(k-2)
    divide_(s_i2, s_q, s_i, s_rm);                        //s_i=floor((2^(k-1))/(2q))

    z = bitSize(s_i);

    for (; ;) {
        for (; ;) {  //generate z-bit numbers until one falls in the range [0,s_i-1]
            randBigInt_(s_R, z, 0);
            if (greater(s_i, s_R))
                break;
        }                //now s_R is in the range [0,s_i-1]
        addInt_(s_R, 1);  //now s_R is in the range [1,s_i]
        add_(s_R, s_i);   //now s_R is in the range [s_i+1,2*s_i]

        copy_(s_n, s_q);
        mult_(s_n, s_R);
        multInt_(s_n, 2);
        addInt_(s_n, 1);    //s_n=2*s_R*s_q+1

        copy_(s_r2, s_R);
        multInt_(s_r2, 2);  //s_r2=2*s_R

        //check s_n for divisibility by small primes up to B
        for (divisible = 0, j = 0; (j < primes.length) && (primes[j] < B); j++)
            if (modInt(s_n, primes[j]) == 0 && !equalsInt(s_n, primes[j])) {
                divisible = 1;
                break;
            }

        if (!divisible)    //if it passes small primes check, then try a single Miller-Rabin base 2
            if (!millerRabinInt(s_n, 2)) //this line represents 75% of the total runtime for randTruePrime_
                divisible = 1;

        if (!divisible) {  //if it passes that test, continue checking s_n
            addInt_(s_n, -3);
            for (j = s_n.length - 1; (s_n[j] == 0) && (j > 0); j--);  //strip leading zeros
            for (zz = 0, w = s_n[j]; w; (w >>= 1), zz++);
            zz += bpe * j;                             //zz=number of bits in s_n, ignoring leading zeros
            for (; ;) {  //generate z-bit numbers until one falls in the range [0,s_n-1]
                randBigInt_(s_a, zz, 0);
                if (greater(s_n, s_a))
                    break;
            }                //now s_a is in the range [0,s_n-1]
            addInt_(s_n, 3);  //now s_a is in the range [0,s_n-4]
            addInt_(s_a, 2);  //now s_a is in the range [2,s_n-2]
            copy_(s_b, s_a);
            copy_(s_n1, s_n);
            addInt_(s_n1, -1);
            powMod_(s_b, s_n1, s_n);   //s_b=s_a^(s_n-1) modulo s_n
            addInt_(s_b, -1);
            if (isZero(s_b)) {
                copy_(s_b, s_a);
                powMod_(s_b, s_r2, s_n);
                addInt_(s_b, -1);
                copy_(s_aa, s_n);
                copy_(s_d, s_b);
                GCD_(s_d, s_n);  //if s_b and s_n are relatively prime, then s_n is a prime
                if (equalsInt(s_d, 1)) {
                    copy_(ans, s_aa);
                    return;     //if we've made it this far, then s_n is absolutely guaranteed to be prime
                }
            }
        }
    }
}
console.log('end')
